
/**
  ******************************************************************************
  * Copyright 2021 The grapilot Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       srv_hal.h
  * @author     baiyang
  * @date       2021-12-27
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>

#include <stdint.h>
#include <stdbool.h>
/*-----------------------------------macro------------------------------------*/
/* Define the CH_n names, indexed from 1, if we don't have them already */
#ifndef CH_1
#define CH_1 0
#define CH_2 1
#define CH_3 2
#define CH_4 3
#define CH_5 4
#define CH_6 5
#define CH_7 6
#define CH_8 7
#define CH_9 8
#define CH_10 9
#define CH_11 10
#define CH_12 11
#define CH_13 12
#define CH_14 13
#define CH_15 14
#define CH_16 15
#define CH_17 16
#define CH_18 17
#define CH_NONE 255
#endif

/*----------------------------------typedef-----------------------------------*/
/*
  output modes. Allows for support of PWM, oneshot and dshot 
*/
// this enum is used by BLH_OTYPE and ESC_PWM_TYPE on AP_Periph
// double check params are still correct when changing
enum output_mode {
    MODE_PWM_NONE,
    MODE_PWM_NORMAL,
    MODE_PWM_ONESHOT,
    MODE_PWM_ONESHOT125,
    MODE_PWM_BRUSHED,
    MODE_PWM_DSHOT150,
    MODE_PWM_DSHOT300,
    MODE_PWM_DSHOT600,
    MODE_PWM_DSHOT1200,
    MODE_NEOPIXEL,  // same as MODE_PWM_DSHOT at 800kHz but it's an LED
    MODE_PROFILED,  // same as MODE_PWM_DSHOT using separate clock and data
};

// https://github.com/bitdump/BLHeli/blob/master/BLHeli_32%20ARM/BLHeli_32%20Firmware%20specs/Digital_Cmd_Spec.txt
enum BLHeliDshotCommand {
    DSHOT_RESET = 0,
    DSHOT_BEEP1 = 1,
    DSHOT_BEEP2 = 2,
    DSHOT_BEEP3 = 3,
    DSHOT_BEEP4 = 4,
    DSHOT_BEEP5 = 5,
    DSHOT_ESC_INFO = 6,
    DSHOT_ROTATE = 7,
    DSHOT_ROTATE_ALTERNATE = 8,
    DSHOT_3D_OFF = 9,
    DSHOT_3D_ON = 10,
    DSHOT_SAVE = 12,
    DSHOT_NORMAL = 20,
    DSHOT_REVERSE = 21,
    DSHOT_LED0_ON = 22,
    DSHOT_LED1_ON = 23,
    DSHOT_LED2_ON = 24,
    DSHOT_LED3_ON = 25,
    DSHOT_LED0_OFF = 26,
    DSHOT_LED1_OFF = 27,
    DSHOT_LED2_OFF = 28,
    DSHOT_LED3_OFF = 29,
};

enum DshotEscType {
    DSHOT_ESC_NONE = 0,
    DSHOT_ESC_BLHELI = 1
};

enum SRVCmd {
    SRV_GET_SAFETY_STATE = 0,
    SRV_SET_FREQ,
    SRV_GET_FREQ,
    SRV_ENABLE_CH,
    SRV_DISABLE_CH,
    SRV_CORK,
    SRV_PUSH,
};

// get output frequency
struct pwm_drv_freq {
    uint16_t chan;
    uint16_t freq;
};

struct pwm_drv_configure {
    rt_uint16_t chan_mask;
    rt_uint16_t pwm_freq; /* pwm frequency in hz */
};

struct srv_configure {
    bool oneshot_enabled;
    bool brushed_enabled;

    uint8_t protocol;
    uint16_t chan_num;
    uint16_t default_freq;
    uint16_t sbus_rate_hz;

    struct pwm_drv_configure pwm_config;
};

struct srv_device {
    struct rt_device parent;
    const struct srv_ops* ops;
};
typedef struct srv_device* srv_dev_t;

struct srv_ops {
    rt_err_t (*dev_init)(srv_dev_t dev);
    rt_err_t (*dev_control)(srv_dev_t dev, int cmd, void* arg);
    rt_size_t (*dev_read)(srv_dev_t dev, uint8_t chan, rt_uint16_t* chan_val, rt_size_t size);
    rt_size_t (*dev_write)(srv_dev_t dev, uint8_t chan, uint16_t pwm, rt_size_t size);
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
rt_err_t hal_srv_register(srv_dev_t dev, const char* name, rt_uint32_t flag, void* data);
/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



